import type { ComponentStyleIdType } from '../../types/interfaces'
import type { SelectOption } from '../select/types'
import { UIComponent } from '../../lib/abstract'
import { ToolKit } from '../../lib/utils/toolkit'
import { ComponentStyleId, logger } from '../../types/constants'
import { RESOURCE_ORIGIN } from '../../types/interfaces'
import { Select } from '../select'
import { TextInput } from '../text_input'

type Type = 'css' | 'js' | 'custom'
type loadType = 'text' | 'json'

export interface textEditorProps {
  id: string
  label: string
  mode: ResourceOrigin
  text: string
  url: string
  type: Type
  timeout?: number
  urlContentType: loadType
  textPlaceholder: string
  urlPlaceholder: string
  selectOptions?: {
    id: string
    label?: string
    options: SelectOption[]
    selectedValue?: string
    clearable?: boolean
    showPlaceholder?: boolean
    placeholder?: string
    onChange?: (value: string | undefined) => void
  }
  onInit?: (instance: TextEditor) => void
  onTextChange: (text: string) => void
  onUrlChange: (url: string, content: string | undefined, hasChanged?: boolean) => void
}

/**
 * 文本编辑器样式类
 */
const TEXT_EDITOR_CLASSES = {
  container: 'text-editor-container',
  editorContent: 'editor-content',
  customTextInput: 'custom-text-input',
  urlInputContainer: 'url-input-container',
  loadBtn: 'load-btn',
  urlPreview: 'url-preview',
  toggleButton: 'toggle-button',
  toggleIcon: 'toggle-icon',
  urlInputWrapper: 'url-input-wrapper',
  statusWrapper: 'url-status-wrapper',
  statusMessage: 'url-status-message',
  statusSuccess: 'success',
  statusError: 'error',
  statusLoading: 'loading',
  modeIndicator: 'mode-indicator',
  modeLocal: 'mode-local',
  modeUrl: 'mode-url',
  headerWrapper: 'header-wrapper',
  selectWrapper: 'select-wrapper',
}

/**
 * 状态类
 */
const STATUS_CLASSES = {
  expanded: 'expanded',
  disabled: 'disabled',
}

type TextEditorClasses = keyof typeof TEXT_EDITOR_CLASSES

export class TextEditor extends UIComponent<textEditorProps> {
  id: string = 'text-editor'
  readonly description: string = '文本编辑器，支持直接编辑和从 URL 加载'
  readonly styleId: string = ComponentStyleId[this.name]
  private isFetching = false // 防止重复请求
  private lastUrl: string = ''
  private hasUrlChanged: boolean = false
  private currentMode: ResourceOrigin
  element: JQuery<HTMLElement> | undefined = undefined
  private readonly selectInstance: Select | undefined

  get name(): ComponentStyleIdType {
    return 'TextEditor'
  }

  get className(): string {
    return TEXT_EDITOR_CLASSES.container
  }

  constructor(props: textEditorProps) {
    super(props)
    this.currentMode = this.props.mode || RESOURCE_ORIGIN.LOCAL

    const { selectOptions } = this.props
    if (selectOptions) {
      this.selectInstance = new Select({
        id: selectOptions.id,
        label: selectOptions.label,
        options: selectOptions.options,
        // 使用 != null 同时检查 undefined 和 null
        ...(selectOptions.selectedValue != null && { selectedValue: selectOptions.selectedValue }),
        ...(selectOptions.clearable != null && { clearable: selectOptions.clearable }),
        ...(selectOptions.showPlaceholder != null && { showPlaceholder: selectOptions.showPlaceholder }),
        ...(selectOptions.placeholder != null && { placeholder: selectOptions.placeholder }),
        onChange: (value: string | undefined) => selectOptions.onChange?.(value),
      })
    }

    // 注册样式
    this.registerStyles()
  }

  ELEMENT_SELECTORS = {
    toggleIcon: { selector: `.${TEXT_EDITOR_CLASSES.toggleIcon}`, dynamic: false, unique: false },
    toggleButton: { selector: `.${TEXT_EDITOR_CLASSES.toggleButton}`, dynamic: false, unique: false },
    loadBtn: { selector: `.${TEXT_EDITOR_CLASSES.loadBtn}`, dynamic: false, unique: false },
    textInput: { selector: `#${this.props.id}-text`, dynamic: false, unique: true },
    urlInput: { selector: `#${this.props.id}-url`, dynamic: false, unique: true },
    urlInputWrapper: { selector: `.${TEXT_EDITOR_CLASSES.urlInputWrapper}`, dynamic: false, unique: false },
    statusWrapper: { selector: `.${TEXT_EDITOR_CLASSES.statusWrapper}`, dynamic: false, unique: false },
    statusMessage: { selector: `.${TEXT_EDITOR_CLASSES.statusMessage}`, dynamic: false, unique: false },
    modeIndicator: { selector: `.${TEXT_EDITOR_CLASSES.modeIndicator}`, dynamic: false, unique: false },
  }

  render(): string {
    const { label, selectOptions } = this.props
    const urlMode = this.currentMode === RESOURCE_ORIGIN.URL
    const expandedClasses = urlMode ? STATUS_CLASSES.expanded : ''
    const hasSelect = !!selectOptions

    return `
      <label>${label}</label>
      <div class="${TEXT_EDITOR_CLASSES.container}">
        <div class="${TEXT_EDITOR_CLASSES.editorContent}">
          <div class="${TEXT_EDITOR_CLASSES.headerWrapper} ${hasSelect ? '' : 'no-select'}">
            ${this.renderSelect()}
            <div class="${TEXT_EDITOR_CLASSES.modeIndicator} ${TEXT_EDITOR_CLASSES[`mode${ToolKit.string.capitalizeFirstLetter(this.currentMode)}` as TextEditorClasses]}">
                ${urlMode ? 'URL模式' : '文本模式'}
            </div>
          </div>
          
          ${this.renderTextInput()}
          
          <button class="${TEXT_EDITOR_CLASSES.toggleButton}">
            <svg class="${TEXT_EDITOR_CLASSES.toggleIcon}" viewBox="0 0 24 24">
              <path d="M7 10l5 5 5-5z"/>
            </svg>
            <span>从URL加载</span>
          </button>
        
          <div class="${TEXT_EDITOR_CLASSES.urlInputWrapper} ${expandedClasses}">
            <div class="${TEXT_EDITOR_CLASSES.urlInputContainer}">
              ${this.renderUrlInput()}
              <button class="${TEXT_EDITOR_CLASSES.loadBtn}">加载</button>
            </div>
          </div>
          <div class="${TEXT_EDITOR_CLASSES.statusWrapper} ${expandedClasses}">
              <div class="${TEXT_EDITOR_CLASSES.statusMessage}"></div>
          </div>
        </div>
      </div>
    `
  }

  /**
   * 渲染文本输入框
   * @returns {string} 文本输入框 HTML
   */
  private renderTextInput(): string {
    const { id, text, textPlaceholder } = this.props

    return new TextInput({
      id: `${id}-text`,
      type: 'textarea',
      rows: 8,
      placeholder: textPlaceholder,
      value: text,
    }).render()
  }

  /**
   * 渲染 URL 输入框
   * @returns {string} URL 输入框 HTML
   */
  private renderUrlInput(): string {
    const { id, url, urlPlaceholder } = this.props

    return new TextInput({
      id: `${id}-url`,
      type: 'url',
      placeholder: urlPlaceholder,
      value: url,
    }).render()
  }

  private renderSelect(): string {
    const { selectOptions } = this.props

    if (!selectOptions || !this.selectInstance)
      return ''

    return `
      <div class="${TEXT_EDITOR_CLASSES.selectWrapper}">
        ${this.selectInstance.render()}
      </div>
    `
  }

  /**
   * 更新模式指示器
   * @param mode 当前模式
   */
  private updateModeIndicator(mode: ResourceOrigin) {
    this.currentMode = mode
    const $modeIndicator = this.getElement('modeIndicator')

    $modeIndicator
      ?.removeClass(`${TEXT_EDITOR_CLASSES.modeLocal} ${TEXT_EDITOR_CLASSES.modeUrl}`)
      .addClass(TEXT_EDITOR_CLASSES[`mode${ToolKit.string.capitalizeFirstLetter(mode)}` as TextEditorClasses])
      .text(mode === RESOURCE_ORIGIN.LOCAL ? '文本模式' : 'URL模式')
  }

  /**
   * 显示状态消息
   */
  private showStatus(
    $element: JQueryElement,
    message: string,
    statusClass: string,
  ) {
    const expanded = $element?.hasClass('expanded')

    $element
      ?.removeClass()
      .addClass(`${TEXT_EDITOR_CLASSES.statusMessage} ${statusClass}`)
      .addClass(expanded ? 'expanded' : '')
      .text(message)
  }

  /**
   * 处理加载
   */
  private async handleLoad() {
    const url = this.getElement('urlInput')?.val() as string | ''

    if (!this.getElement('urlInput') || !url || url.length === 0)
      return

    const $statusMessage = this.getElement('statusMessage')

    try {
      this.showStatus($statusMessage, '正在加载...', TEXT_EDITOR_CLASSES.statusLoading)

      const data = await this.loadUrlContent(
        this.getElement('urlInput')?.val() as string,
        this.props.urlContentType,
        this.props.timeout,
      )

      const content = data.data
      const duration = data.duration

      // 字符串长度限制
      const limit = 500
      this.showStatus(
        $statusMessage,
        `加载成功，用时 ${duration} ms，返回内容的前${limit}个字符：${content.substring(0, limit)}${content.length > limit ? '...' : ''}`,
        TEXT_EDITOR_CLASSES.statusSuccess,
      )

      this.props.onUrlChange(url, content)
    }
    catch (error: any) {
      logger.error(`[${this.name}] 加载URL失败:`, error)
      this.showStatus(
        $statusMessage,
        `加载失败: ${error.message}`,
        TEXT_EDITOR_CLASSES.statusError,
      )
    }
  }

  handleTextChange(): void {
    const value = this.getElement('textInput')?.val() as string
    // 文本输入值为空且下拉框选项值不为空时触发恢复默认提示
    if (value.length === 0 && this.selectInstance && this.props?.selectOptions?.showPlaceholder != null) {
      const currentValue = this.selectInstance.getValue()
      if (currentValue !== undefined && currentValue !== '') {
        this.selectInstance.setValue('')
      }
    }
    this.props.onTextChange(value)
    this.updateModeIndicator(RESOURCE_ORIGIN.LOCAL)
  }

  handleUrlChange(): void {
    const value = this.getElement('urlInput')?.val() as string
    const $statusMessage = this.getElement('statusMessage')

    // 检测URL是否实际发生变化（忽略聚焦/失焦导致的重复触发）
    if (value !== this.lastUrl) {
      logger.info(`[${this.name}] URL变化：\n1）旧：${this.lastUrl} \n2）新：${value}`)
      this.hasUrlChanged = true
      this.lastUrl = value
    }

    if (this.hasUrlChanged) {
      this.props.onUrlChange(value, undefined, this.hasUrlChanged)
      // 仅在实际有变化且 URL 不为空时显示提示
      if (value.length > 0) {
        this.showStatus(
          $statusMessage,
          `检测到URL变化，请点击加载按钮加载新内容`,
          TEXT_EDITOR_CLASSES.statusLoading,
        )
      }
    }
    // URL 被清空时重置状态
    if (value.length === 0) {
      this.hasUrlChanged = false
      $statusMessage?.removeClass().addClass(TEXT_EDITOR_CLASSES.statusMessage)
    }

    this.lastUrl = value
    this.updateModeIndicator(RESOURCE_ORIGIN.URL)
  }

  bindEvents(): void {
    const { onInit } = this.props

    // 挂载下拉框
    this.selectInstance?.mount($(this.selector))

    // 折叠按钮点击
    this.getElement('toggleButton')?.on('click', () => {
      this.getElement('urlInputWrapper')?.toggleClass(STATUS_CLASSES.expanded)
      this.getElement('statusWrapper')?.toggleClass(STATUS_CLASSES.expanded)
      this.getElement('toggleIcon')?.toggleClass(`is-${STATUS_CLASSES.expanded}`)
      const $statusWrapper = this.getElement('statusWrapper')
      // 折叠时重置消息样式
      if (!$statusWrapper?.hasClass(STATUS_CLASSES.expanded))
        this.getElement('statusMessage')?.removeClass().addClass(TEXT_EDITOR_CLASSES.statusMessage)
    })

    // 加载按钮点击
    const $loadBtn = this.getElement('loadBtn')
    $loadBtn?.on('click', async (e) => {
      const $element = $(e.currentTarget)

      try {
        $element.prop(STATUS_CLASSES.disabled, true).text('加载中...')
        await this.handleLoad()
      }
      finally {
        $element.prop(STATUS_CLASSES.disabled, false).text('加载')
      }
    })

    const $textInput = this.getElement('textInput')
    // 文本输入变化和失焦
    $textInput
      ?.on('blur', () => this.handleTextChange())
      ?.on('keydown', (e) => {
        const $element = $(e.currentTarget)

        if (e.key === 'Enter') {
          // 判断是否按下了 Shift 键
          if (e.shiftKey) {
            // Shift+Enter: 插入换行
            return true // 允许默认行为（换行）
          }
          else {
            // 纯Enter: 触发表单提交
            e.preventDefault() // 阻止默认换行行为
            this.handleUrlChange()
            $element.trigger('blur')
          }
        }
      })
    $textInput?.on('focus', () => this.updateModeIndicator(RESOURCE_ORIGIN.LOCAL))

    // URL失焦、回车事件
    const $urlInput = this.getElement('urlInput')
    $urlInput
      ?.on('blur', () => this.handleUrlChange())
      .on('keydown', (e) => {
        const $element = $(e.currentTarget)

        if (e.key === 'Enter') {
          this.handleUrlChange()
          $element.trigger('blur')
        }
      })
    $urlInput?.on('focus', (e) => {
      const $element = $(e.currentTarget)
      this.lastUrl = $element?.val() as string
      this.updateModeIndicator(RESOURCE_ORIGIN.URL)
    })

    onInit?.(this)
  }

  /**
   * 获取 URL 数据
   * @param url URL
   * @param type 类型
   * @param timeout 超时时间
   * @returns 返回数据及加载耗时(毫秒)
   */
  private loadUrlContent = (url: string, type: loadType, timeout: number | undefined): Promise<{ data: any, duration: number }> => {
    return new Promise((resolve, reject) => {
      if (this.isFetching) {
        reject(new Error('请求正在进行中'))
        return
      }

      this.isFetching = true
      const startTime = performance.now() // 记录开始时间

      $.ajax({
        url,
        timeout: timeout || 5000,
        dataType: type || 'text', // 明确指定响应类型
        success: (data) => {
          const duration = Math.round(performance.now() - startTime) // 计算耗时
          logger.debug(`[${this.name}] 加载成功, 耗时: ${duration}ms`)
          resolve({ data, duration }) // 直接解析文本内容
        },
        error: (_xhr, status, error) => {
          const duration = Math.round(performance.now() - startTime)
          reject(new Error(`HTTP错误! 耗时: ${duration}ms，状态: ${status}, 错误: ${error}`))
        },
        complete: () => {
          this.isFetching = false
        },
      })
    })
  }

  getStyles(): string {
    return styles()
  }

  setTextValue(text: string): void {
    this.getElement('textInput')?.val(text)
    this.handleTextChange()
  }

  reset(): void {
    super.reset()

    // 重置文本输入
    this.getElement('textInput')?.val('').trigger('blur')
    // 重置 URL 输入
    this.getElement('urlInput')?.val('').trigger('blur')
    // 重置模式
    this.updateModeIndicator(RESOURCE_ORIGIN.LOCAL)
    // 重置状态
    this.getElement('statusMessage')?.removeClass().addClass(TEXT_EDITOR_CLASSES.statusMessage)
  }
}

function styles(): string {
  return `
    .${TEXT_EDITOR_CLASSES.container} {
      all: initial !important;
      display: flex !important;
      flex-direction: column !important;
      gap: 12px !important;
      width: 100% !important;

      .${TEXT_EDITOR_CLASSES.editorContent} {
        display: flex !important;
        flex-direction: column !important;
        gap: 10px !important;
        padding-top: 18px !important;
        
        .${TEXT_EDITOR_CLASSES.headerWrapper} {
          display: flex !important;
          justify-content: space-between !important;
          align-items: center !important;
          position: relative !important;
          margin-bottom: 4px !important;
          
          &.no-select {
            /* 没有 select 时的样式 */
            justify-content: flex-end !important;
          }
          
          .${TEXT_EDITOR_CLASSES.selectWrapper} {
            flex: 1 !important;
            margin-right: 8px !important;
            display: flex;
            align-items: center !important;
            justify-content: flex-start !important;
            label {
              min-width: unset !important;
              margin-right: 8px !important;
            }
          }
        
          .${TEXT_EDITOR_CLASSES.modeIndicator} {
            padding: 2px 6px !important;
            font-size: 8px !important;
            border-radius: 10px !important;
            font-weight: bold !important;
            
            &.${TEXT_EDITOR_CLASSES.modeLocal} {
              background: #6c757d !important;
              color: #ffffff !important;
            }
            
            &.${TEXT_EDITOR_CLASSES.modeUrl} {
              background: #6d5ffd !important;
              color: #ffffff !important;
            }
          }
        }

        .${TEXT_EDITOR_CLASSES.toggleButton} {
          all: initial;
          display: inline-flex !important;
          align-items: center;
          justify-content: flex-end;
          gap: 4px;
          padding: 2px 4px;
          background: #f8f9fa;
          border-radius: 4px;
          cursor: pointer;
          font-size: 14px;
          color: #0d6efd; // 蓝色文字
          font-weight: 500; // 加粗
          transition: all 0.2s ease;
          margin: 8px 0;
          width: auto;
          margin-left: auto;
          border: 1px solid transparent; // 添加透明边框防止跳动
          
          &:hover {
            background: #e9ecef;
          }
          .${TEXT_EDITOR_CLASSES.toggleIcon} {
            width: 16px;
            height: 16px;
            fill: currentColor;
            transition: transform 0.2s ease;
          }
          .${TEXT_EDITOR_CLASSES.toggleIcon}.is-${STATUS_CLASSES.expanded} {
            transform: rotate(180deg);
          }
        }
        
        .${TEXT_EDITOR_CLASSES.statusWrapper} {
          display: none;
        
          &.${STATUS_CLASSES.expanded} {
            display: block;
          }
        
          .${TEXT_EDITOR_CLASSES.statusMessage} {
            margin-top: 8px;
            font-size: 13px;
            padding: 6px 8px;
            border-radius: 4px;
            display: none;

            &.${TEXT_EDITOR_CLASSES.statusLoading} {
              display: block;
              color: #0d6efd;
              background: #e7f1ff;
            }
            
            &.${TEXT_EDITOR_CLASSES.statusSuccess} {
              display: block;
              color: #198754;
              background: #e8f7ee;
            }
            
            &.${TEXT_EDITOR_CLASSES.statusError} {
              display: block;
              color: #dc3545;
              background: #fce8e8;
            }
          }
        }
          
        .${TEXT_EDITOR_CLASSES.urlInputWrapper} {
          max-height: 0;
          overflow: hidden;
          
          &.${STATUS_CLASSES.expanded} {
            max-height: 100px; /* 根据内容调整 */
          }

          .${TEXT_EDITOR_CLASSES.urlInputContainer} {
            display: flex !important;
            justify-content: space-between !important;
            align-items: center !important;
            gap: 8px !important;
            
            input {
              flex: 1 !important;
            }

            .${TEXT_EDITOR_CLASSES.loadBtn} {
              all: initial !important;
              padding: 8px 16px !important;
              background: #0d6efd !important;
              color: white !important;
              border-radius: 4px !important;
              font-size: 14px !important;
              cursor: pointer !important;
              transition: all 0.2s ease !important;
              
              &:hover {
                background: #0b5ed7 !important;
              }
            }
          }
        }
      }
    }
  `
}
